/*:
* @plugindesc (v1.03)地图载入效果
* @author 小c
* @version 1.0.3
* @date 3/18/2020
*
* @param Battle Bgm Pitch
* @text 战斗BGM音调
* @type number
* @default 100
*
* @param Battle Bgm Volume
* @text 战斗BGM音量
* @type number
* @default 90
*
* @param Battle Bgm Pan
* @text 战斗BGM声像
* @type number
* @default 0
*
* @param Map Tint Duration
* @text 地图色调转变时间
* @type number
* @min 1
* @default 1
*
* @param Default Map Tint
* @text 地图默认色调
* @desc 色调由四个数字构成，中间用英文逗号分隔
* 四个参数的含义与Map Tint标签说明一致
* @default 0, 0, 0, 0
*
* @param Use Save Mode
* @text 是否启用存档模式选项
* @type boolean
* @on 启用
* @off 不启用
* @desc 关闭后，载入地图时将不改变存档模式
* @default true
*  
* @help
* 地图载入效果，在地图完全加载完成后执行额外内容。
* 
* 地图标签
* <Battle Bgm: name, pitch, volume, pan>
* 地图战斗BGM设置，其中pitch【音调】、volume【音量】、pan【声像】为可选，
* 不设置时按插件参数配置。
*
* <Map Tint: red, green, blue, grey>
* 指定地图色调，四个参数依次为 红 绿 蓝 灰度
*
* 改变地图存档模式，默认所有地图允许存档
* <Map Cannot Save> 该地图禁止存档
*
* <Load Map Effect Eval>
* //JavaScript code
* $gameScreen.startTint([20, 20, 20, 68], 60);
* </Load Map Effect Eval>
* 地图载入执行额外代码
*
* 若想在事件中执行地图载入效果，请使用下面的插件指令
* ExecuteMapLoadEffect mode
* 执行mode所指向的载入效果，mode取值如下
* save：强制修改存档状态为地图存档模式，此时插件参数的配置将被忽略
* battleBgm：重置战斗BGM为地图战斗BGM
* tint：重置画面色调
* eval：执行载入代码
* 此插件指令在战斗中无效
*
* 更新日志
* v1.00
* 插件完成
*
* v1.01
* 增加地图存档模式的指定
*
* v1.02
* 修复打开插件后无法进行事件测试的问题
*
* v1.03
* 修复从有色调配置的地图进入没有配置的地图时地图色调不恢复默认的问题
*/

var Imported = Imported || {};
Imported.CP_LoadMapEffect = true;

var LoadMapManager = LoadMapManager || {};
var params = PluginManager.parameters("CP_LoadMapEffect");

LoadMapManager.BATTLE_BGM_PROPERTIES = {};
LoadMapManager.BATTLE_BGM_PROPERTIES.pitch = Number(params["Battle Bgm Pitch"]) || 0;
LoadMapManager.BATTLE_BGM_PROPERTIES.volume = Number(params["Battle Bgm Volume"]) || 90;
LoadMapManager.BATTLE_BGM_PROPERTIES.pan = Number(params["Battle Bgm Pan"]) || 0;

LoadMapManager.MAP_TINT_DURATION = Number(params["Map Tint Duration"]) || 1;
LoadMapManager.USE_SAVE_MODE = eval(params["Use Save Mode"]) || false;

LoadMapManager.MAP_TINT_PARAM = params["Default Map Tint"].split(",");
LoadMapManager.DEFAULT_MAP_TINT = new Array(4);
for(var i = 0; i < 4; i++){
    var s = Number(LoadMapManager.MAP_TINT_PARAM[i]) || 0;
    LoadMapManager.DEFAULT_MAP_TINT[i] = s; 
}

LoadMapManager.MAP_LOADED = DataManager.isMapLoaded;
DataManager.isMapLoaded = function(){
    if(!LoadMapManager.MAP_LOADED.call(this))
        return false;

    LoadMapManager.loadMapSaveMode();
    LoadMapManager.loadMapBattleBgm();
    LoadMapManager.loadMapTint();
    LoadMapManager.loadMapEffectCode();

    return true;
};

LoadMapManager.loadMapBattleBgm = function(){
    $dataMap.battleBgm = null;
    var battleBgm = null;

    if($dataMap.meta && $dataMap.meta["Battle Bgm"]){
        var data = $dataMap.meta["Battle Bgm"].split(",");
        battleBgm = {};
        if(data[0] && data[0].trim() !== ""){
            battleBgm.name = data[0].trim();
            battleBgm.pitch = Number(data[1]) || this.BATTLE_BGM_PROPERTIES.pitch;
            battleBgm.volume = Number(data[2]) || this.BATTLE_BGM_PROPERTIES.volume;
            battleBgm.pan = Number(data[3]) || this.BATTLE_BGM_PROPERTIES.pan;
        }
    }

    if(battleBgm && battleBgm.name)
        $dataMap.battleBgm = battleBgm;
};

LoadMapManager.loadMapTint = function(){
    $dataMap.tint =JSON.parse(JSON.stringify(this.DEFAULT_MAP_TINT));
    if($dataMap.meta && $dataMap.meta["Map Tint"]){
        var data = $dataMap.meta["Map Tint"].split(",");
        if(data.length >= 4){
            for(var i = 0; i < 4; i++)
                $dataMap.tint[i] = Number(data[i]) || 0;
        }
    }
};

LoadMapManager.loadMapEffectCode = function(){
    $dataMap.loadEffectCode = null;

    if($dataMap.meta && $dataMap.meta["Load Map Effect Eval"]){
        var reg = /<Load Map Effect Eval>([\s\S]*)<\/Load Map Effect Eval>/;
        reg.exec($dataMap.note);

        $dataMap.loadEffectCode = RegExp.$1;
    }
};

LoadMapManager.loadMapSaveMode = function(){
    $dataMap.canSave = true;

    if($dataMap.meta && $dataMap.meta["Map Cannot Save"])
        $dataMap.canSave = false;
};

//----------------------------------
//        DataManager 
//----------------------------------
LoadMapManager.LOAD_GAME = DataManager.loadGame;
DataManager.loadGame = function(savefileId){
    if(!LoadMapManager.LOAD_GAME.call(this, savefileId))
        return false;

    LoadMapManager._isGameLoaded = true;

    return true;
};

//----------------------------------
//        Scene_Map 
//----------------------------------
LoadMapManager.START_MAP = Scene_Map.prototype.start;
Scene_Map.prototype.start = function() {
    LoadMapManager.START_MAP.call(this);

    $gameMap.processLoadEffect();
    LoadMapManager._isGameLoaded = false;
};

//----------------------------------
//        Game_Map 
//----------------------------------

//先于Scene_Map的start方法执行
LoadMapManager.SETUP_MAP = Game_Map.prototype.setup;
Game_Map.prototype.setup = function(mapId){
    LoadMapManager.SETUP_MAP.call(this, mapId);
    
    this._battleBgm = $dataMap.battleBgm;
    this._tint = $dataMap.tint;
    this._loadEffectCode = $dataMap.loadEffectCode;
    this._canSave = $dataMap.canSave;

    if(!LoadMapManager._isGameLoaded)
        $gameSystem.setHasEvalEffect(false);
    
    LoadMapManager._isGameLoaded = false;
};

Game_Map.prototype.mapBattleBgm = function(){
    return this._battleBgm;
};

Game_Map.prototype.mapTint = function(){
    return this._tint;
};

Game_Map.prototype.canSave = function(){
    return this._canSave;
};

Game_Map.prototype.loadEffectCode = function(){
    return this._loadEffectCode;
};

Game_Map.prototype.executeTint = function(){
    $gameScreen.startTint(this.mapTint(), LoadMapManager.MAP_TINT_DURATION);
};

Game_Map.prototype.executeBattleBgm = function(){
    if(this.mapBattleBgm()){
        $gameSystem.setBattleBgm(this.mapBattleBgm());
    }
};

Game_Map.prototype.evalLoadEffectCode = function(){
    var code = this.loadEffectCode();

    try{
        eval(code);
    }catch(err){
        console.error(err);
    }
};

Game_Map.prototype.executeSaveMode = function(){
    if(this.canSave())
        $gameSystem.enableSave();
    else
        $gameSystem.disableSave();
};

Game_Map.prototype.processLoadEffect = function(){
    if(!$gameSystem.hasEvalEffect()){
        if(LoadMapManager.USE_SAVE_MODE)
            this.executeSaveMode();
        this.executeBattleBgm();
        this.executeTint();
        this.evalLoadEffectCode();
        $gameSystem.setHasEvalEffect(true);
    }
};

//----------------------------------
//        Game_System 
//----------------------------------
LoadMapManager.INIT_SYSTEM = Game_System.prototype.initialize;
Game_System.prototype.initialize = function(){
    LoadMapManager.INIT_SYSTEM.call(this);

    this.setHasEvalEffect(false);
};

Game_System.prototype.setHasEvalEffect = function(has){
    this._hasEvalEffect = has;
};

Game_System.prototype.hasEvalEffect = function(){
    return !!this._hasEvalEffect;
};

//----------------------------------
//        Game_Interpreter 
//----------------------------------
LoadMapManager.PLUGIN_COMMAND = Game_Interpreter.prototype.pluginCommand;
Game_Interpreter.prototype.pluginCommand = function(command, args){
    LoadMapManager.PLUGIN_COMMAND.call(this, command, args);

    if(command == 'ExecuteMapLoadEffect' && !$gameParty.inBattle()){
        var mode = args[0].toUpperCase();
        switch(mode){
            case "BATTLEBGM":
                $gameMap.executeBattleBgm();
                break;
            case "TINT":
                $gameMap.executeTint();
                break;
            case "EVAL":
                $gameMap.evalLoadEffectCode();
                break;
            case "SAVE":
                $gameMap.executeSaveMode();
                break;
        }
    }
};